﻿using SFast.Enums;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace SFast
{
    /// <summary>
    /// 发起http请求的帮助类
    /// </summary>
    public static class HttpRequestHelper
    {
        #region get请求方法

        /// <summary>
        /// 发起get请求
        /// contentType默认：application/json;charset=UTF-8。
        /// </summary>
        /// <param name="url">请求的url</param>
        /// <returns>返回请求的文本</returns>
        public static string Get(String url)
        {
            return Get(url, null, null, null, null, null);
        }

        /// <summary>
        /// 发起get请求
        /// </summary>
        /// <param name="url">请求的url</param>
        /// <param name="contentType">发起请求时的contentType。默认：application/json;charset=UTF-8。
        /// 其它值请选择枚举RequestContentType的_GetRemark()获取 或 自己手写</param>
        /// <returns>返回请求的文本</returns>
        public static string Get(String url, String contentType)
        {
            return Get(url, contentType, null, null, null, null);
        }

        /// <summary>
        /// 发起get请求
        /// </summary>
        /// <param name="url">请求的url</param>
        /// <param name="onResponseAfter">请求结束后的事件。 参数：Response对象 </param>
        /// <returns>返回请求的文本</returns>
        public static string Get(String url,  Action<HttpWebResponse> onResponseAfter)
        {
            return Get(url, null, null, null, null, onResponseAfter);
        }

        /// <summary>
        /// 发起get请求
        /// </summary>
        /// <param name="url">请求的url</param>
        /// <param name="contentType">发起请求时的contentType。默认：application/json;charset=UTF-8。 其它值请选择枚举RequestContentType的_GetRemark()该当 或 自己手写</param>
        /// <param name="onResponseAfter">请求结束后的事件。 参数：Response对象 </param>
        /// <returns>返回请求的文本</returns>
        public static string Get(String url, String contentType, Action<HttpWebResponse> onResponseAfter)
        {
            return Get(url, contentType, null, null, null, onResponseAfter);
        }

        /// <summary>
        /// 发起get请求
        /// </summary>
        /// <param name="url">请求的url</param>
        /// <param name="contentType">发起请求时的contentType。默认：application/json;charset=UTF-8。
        /// 其它值请选择枚举RequestContentType的_GetRemark()该当 或 自己手写</param>
        /// <param name="timeout">设置超时时间。默认：30000毫秒</param>
        /// <param name="userAgent">设置 User-agentHTTP 标头的值。</param>
        /// <param name="cookies">设置与此请求关联的 cookie。</param>
        /// <param name="onResponseAfter">请求结束后的事件。
        /// 参数：Response对象 </param>
        /// <returns>返回请求的文本</returns>
        public static string Get(String url, String contentType, int? timeout, String userAgent, CookieCollection cookies,Action<HttpWebResponse> onResponseAfter)
        {
            HttpWebRequest request = null;
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                //对服务端证书进行有效性校验（非第三方权威机构颁发的证书，如自己生成的，不进行验证，这里返回true）
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request = WebRequest.Create(url) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version10;    //http版本，默认是1.1,这里设置为1.0
            }
            else
            {
                request = (HttpWebRequest)HttpWebRequest.Create(url);
            }
            request.Method = "GET";

            //设置上传服务的数据格式  
            if (String.IsNullOrEmpty(contentType))
            {
                request.ContentType = RequestContentType.application_json_charset_UTF8._GetRemark();
            }
            else
            {
                request.ContentType = contentType;
            }
            //请求的身份验证信息为默认  
            request.Credentials = CredentialCache.DefaultCredentials;
            if (timeout.HasValue)
            {
                //请求超时时间  
                request.Timeout = timeout.Value;
            }
            else
            {
                request.Timeout = 30000;
            }
            

            if (!string.IsNullOrEmpty(userAgent))
            {
                request.UserAgent = userAgent;
            }
            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            } 

            //读取返回消息  
            string res = "";
                var response = (HttpWebResponse)request.GetResponse();
                var reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                res = reader.ReadToEnd();
                reader.Close();
                response.Close();
            if (onResponseAfter != null)
	{
		 onResponseAfter(response);
	}
            return res;
        }

        #endregion

        #region post请求方法
        /// <summary>
        /// 发起post请求
        /// contentType: 默认：application/json;charset=UTF-8
        /// </summary>
        /// <param name="url">请求url</param>
        /// <param name="postData">post请求时post的数据。默认：Encoding.UTF8</param>
        /// <returns>返回请求的文本</returns>
        public static String Post(String url, String postData)
        {
            return Post(url, postData, null, null, null, null, null, null);
        }

        
        /// <summary>
        /// 发起post请求
        /// contentType: 默认：application/json;charset=UTF-8
        /// </summary>
        /// <param name="url">请求url</param>
        /// <param name="postData">post请求时post的数据。默认：Encoding.UTF8</param>
        /// <param name="contentType">发起请求时的contentType。默认：application/json;charset=UTF-8。</param>
        /// <returns>返回请求的文本</returns>
        public static String Post(String url, String postData, String contentType)
        {
            return Post(url, postData, contentType, null, null, null, null, null);
        }

        /// <summary>
        /// 发起post请求
        /// contentType: 默认：application/json;charset=UTF-8
        /// </summary>
        /// <param name="url">请求url</param>
        /// <param name="postData">post请求时post的数据。默认：Encoding.UTF8</param>
        /// <param name="contentType">发起请求时的contentType。默认：application/json;charset=UTF-8。 其它值请选择枚举RequestContentType的_GetRemark()该当 或 自己手写</param>
        /// <param name="onResponseAfter">请求结束后的事件。 参数：Response对象 </param>
        /// <returns>返回请求的文本</returns>
        public static String Post(String url, String postData, String contentType,Action<HttpWebResponse> onResponseAfter)
        {
            return Post(url, postData, contentType, null, null, null, null, onResponseAfter);
        }

        /// <summary>
        /// 发起post请求
        /// </summary>
        /// <param name="url">请求url</param>
        /// <param name="postData">post请求时post的数据</param>
        /// <param name="contentType">发起请求时的contentType。默认：application/json;charset=UTF-8。
        /// 其它值请选择枚举RequestContentType的_GetRemark()该当 或 自己手写</param>
        /// <param name="timeout">设置超时时间。默认：30000毫秒</param>
        /// <param name="userAgent">获取或设置 User-agentHTTP 标头的值。</param>
        /// <param name="requestEncoding">post数据的编码格式。默认：Encoding.UTF8</param>
        /// <param name="cookies">设置与此请求关联的 cookie。</param>
        /// <param name="onResponseAfter">请求结束后的事件。
        /// 参数：Response对象 </param>
        /// <returns>返回请求的文本</returns>
        public static String Post(String url, String postData,String contentType, int? timeout,string userAgent, 
                                Encoding requestEncoding, CookieCollection cookies,Action<HttpWebResponse> onResponseAfter)
        {
            String result = String.Empty;
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (requestEncoding == null)
            {
                requestEncoding = Encoding.UTF8;
            }
            HttpWebRequest request = null;
            //如果是发送HTTPS请求  
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request = WebRequest.Create(url) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version10;
            }
            else
            {
                request = WebRequest.Create(url) as HttpWebRequest;
            }
            request.Method = "POST";
            if (String.IsNullOrEmpty(contentType))
            {
                request.ContentType = RequestContentType.application_json_charset_UTF8._GetRemark();
            }
            else
            {
                request.ContentType = contentType;
            }
            

            if (!string.IsNullOrEmpty(userAgent))
            {
                request.UserAgent = userAgent;
            }

            if (timeout.HasValue)
            {
                request.Timeout = timeout.Value;
            }
            else
            {
                request.Timeout = 30000;
            }
            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }

            postData = postData == null ? String.Empty : postData;
            byte[] byteArray = requestEncoding.GetBytes(postData); //转化
            request.ContentLength = byteArray.Length;
            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(byteArray, 0, byteArray.Length);
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
            result = sr.ReadToEnd();
            sr.Close();
            response.Close();
            if (onResponseAfter!= null)
            {
                onResponseAfter(response);
            }
            return result;  
        }
        #endregion

        #region 辅助方法 与 枚举
        /// <summary>
        /// 验证证书
        /// </summary>
        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            if (errors == SslPolicyErrors.None)
                return true;
            return false;
        }

        public enum RequestContentType
        {
            /// <summary>
            /// application/x-www-form-urlencoded
            /// </summary>
            [Remark("application/x-www-form-urlencoded")]
            application_x_www_form_urlencoded,

            /// <summary>
            /// application/json;charset=UTF-8
            /// </summary>
            [Remark("application/json;charset=UTF-8")]
            application_json_charset_UTF8
        }
        #endregion
    }
}
